﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace Sinacor.Infra.UI.Controls.SmartClient
{
    public class SinacorWindowContent : ContentControl
    {
        public SinacorWindowContent()
        {
            this.Loaded += new RoutedEventHandler(SinacorWindowContent_Loaded);
        }

        private double _verticalMargin = 0;
        private double _horizontalMargin = 0;

        private void SinacorWindowContent_Loaded(object sender, RoutedEventArgs e)
        {
            // margem esquerda (11)
            SinacorWindow window = (SinacorWindow)Window.GetWindow(this);

            if (!window.IsClosed)
            {
                double right = this.PointToScreen(new Point()).X - window.PointToScreen(new Point()).X;

                //margem direita (16)
                double left = Window.GetWindow(this).PointToScreen(new Point(Window.GetWindow(this).ActualWidth, Window.GetWindow(this).ActualHeight)).X - this.PointToScreen(new Point(this.ActualWidth, this.ActualHeight)).X;

                _horizontalMargin = right + left;

                this.CoerceValue(MinWidthProperty);

                // margem topo (42)
                double top = this.PointToScreen(new Point()).Y - Window.GetWindow(this).PointToScreen(new Point()).Y;

                // margem bottom (26)
                double bottom = Window.GetWindow(this).PointToScreen(new Point(Window.GetWindow(this).ActualWidth, Window.GetWindow(this).ActualHeight)).Y - this.PointToScreen(new Point(this.ActualWidth, this.ActualHeight)).Y;

                _verticalMargin = top + bottom;

                this.CoerceValue(MinHeightProperty);
            }
        }

        static SinacorWindowContent()
        {
            MinWidthProperty.OverrideMetadata(typeof(SinacorWindowContent), new FrameworkPropertyMetadata(null, CoerceMinWidth));
            MinHeightProperty.OverrideMetadata(typeof(SinacorWindowContent), new FrameworkPropertyMetadata(null, CoerceMinHeight));

            MaxWidthProperty.OverrideMetadata(typeof(SinacorWindowContent), new FrameworkPropertyMetadata(null, CoerceMaxWidth));
            MaxHeightProperty.OverrideMetadata(typeof(SinacorWindowContent), new FrameworkPropertyMetadata(null, CoerceMaxHeight));
        }

        #region AutoContentWidth
        public static readonly DependencyProperty AutoContentWidthProperty = DependencyProperty.Register("AutoContentWidth", typeof(bool), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(true, OnAutoContentWidthChanged));
        /// <summary>
        /// Indica se o conteúdo da janela tem largura automática
        /// </summary>
        public bool AutoContentWidth
        {
            get { return (bool)GetValue(AutoContentWidthProperty); }
            set { SetValue(AutoContentWidthProperty, value); }
        }

        private static void OnAutoContentWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MinWidthProperty);
            windowContent.CoerceValue(MaxWidthProperty);
        }
        #endregion

        #region AutoContentHeight
        public static readonly DependencyProperty AutoContentHeightProperty = DependencyProperty.Register("AutoContentHeight", typeof(bool), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(true, OnAutoContentHeightChanged));
        /// <summary>
        /// Indica se o conteúdo da janela tem altura automática
        /// </summary>
        public bool AutoContentHeight
        {
            get { return (bool)GetValue(AutoContentHeightProperty); }
            set { SetValue(AutoContentHeightProperty, value); }
        }

        private static void OnAutoContentHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MinHeightProperty);
            windowContent.CoerceValue(MaxHeightProperty);
        }
        #endregion

        #region InitialWindowWidth
        public static readonly DependencyProperty InitialWindowWidthProperty = DependencyProperty.Register("InitialWindowWidth", typeof(double), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(double.NaN, OnInitialWindowWidthChanged));
        /// <summary>
        /// Largura inicial da janela
        /// </summary>
        public double InitialWindowWidth
        {
            get { return (double)GetValue(InitialWindowWidthProperty); }
            set { SetValue(InitialWindowWidthProperty, value); }
        }

        private static void OnInitialWindowWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MinWidthProperty);
        }
        #endregion

        #region InitialWindowHeight
        public static readonly DependencyProperty InitialWindowHeightProperty = DependencyProperty.Register("InitialWindowHeight", typeof(double), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(double.NaN, OnInitialWindowHeightChanged));
        /// <summary>
        /// Altura inicial da janela
        /// </summary>
        public double InitialWindowHeight
        {
            get { return (double)GetValue(InitialWindowHeightProperty); }
            set { SetValue(InitialWindowHeightProperty, value); }
        }

        private static void OnInitialWindowHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MinHeightProperty);
        }
        #endregion

        #region ContentWidth
        public static readonly DependencyProperty ContentWidthProperty = DependencyProperty.Register("ContentWidth", typeof(double), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(double.NaN, OnContentWidthChanged));
        /// <summary>
        /// Largura do conteúdo da janela
        /// </summary>
        public double ContentWidth
        {
            get { return (double)GetValue(ContentWidthProperty); }
            set { SetValue(ContentWidthProperty, value); }
        }

        private static void OnContentWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MaxWidthProperty);
        }
        #endregion

        #region ContentHeight
        public static readonly DependencyProperty ContentHeightProperty = DependencyProperty.Register("ContentHeight", typeof(double), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(double.NaN, OnContentHeightChanged));
        /// <summary>
        /// Altura do conteúdo da janela
        /// </summary>
        public double ContentHeight
        {
            get { return (double)GetValue(ContentHeightProperty); }
            set { SetValue(ContentHeightProperty, value); }
        }

        private static void OnContentHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MaxHeightProperty);
        }
        #endregion

        #region WindowZoom
        public static readonly DependencyProperty WindowZoomProperty = DependencyProperty.Register("WindowZoom", typeof(int), typeof(SinacorWindowContent), new FrameworkPropertyMetadata(100, OnWindowZoomChanged));
        /// <summary>
        /// Zoom atual da janela
        /// </summary>
        public int WindowZoom
        {
            get { return (int)GetValue(WindowZoomProperty); }
            set { SetValue(WindowZoomProperty, value); }
        }

        private static void OnWindowZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            windowContent.CoerceValue(MinWidthProperty);
            windowContent.CoerceValue(MinHeightProperty);
        }
        #endregion

        private static object CoerceMinWidth(DependencyObject d, object value)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            if (windowContent.AutoContentWidth &&
                !double.IsNaN(windowContent.InitialWindowWidth))
            {
                value = (double)((windowContent.InitialWindowWidth - windowContent._horizontalMargin) * ((double)windowContent.WindowZoom / 100));
            }
            else
            {
                value = (double)0;
            }

            return value;
        }

        private static object CoerceMinHeight(DependencyObject d, object value)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            if (windowContent.AutoContentHeight &&
                !double.IsNaN(windowContent.InitialWindowHeight))
            {
                value = (double)((windowContent.InitialWindowHeight - windowContent._verticalMargin) * ((double)windowContent.WindowZoom / 100));
            }
            else
            {
                value = (double)0;
            }

            return value;
        }

        private static object CoerceMaxWidth(DependencyObject d, object value)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            if (windowContent.AutoContentWidth &&
                !double.IsNaN(windowContent.ContentWidth))
            {
                value = windowContent.ContentWidth;
            }
            else
            {
                value = double.PositiveInfinity;
            }

            return value;
        }

        private static object CoerceMaxHeight(DependencyObject d, object value)
        {
            SinacorWindowContent windowContent = (SinacorWindowContent)d;

            if (windowContent.AutoContentHeight &&
                !double.IsNaN(windowContent.ContentHeight))
            {
                value = windowContent.ContentHeight;
            }
            else
            {
                value = double.PositiveInfinity;
            }

            return value;
        }

        //SinacorScrollViewer _scrollViewer;

        //protected override void OnVisualParentChanged(DependencyObject oldParent)
        //{
        //    base.OnVisualParentChanged(oldParent);

        //    // Captura o scrollviewer da janela
        //    _scrollViewer = ControlHelper.FindParent(this, typeof(SinacorScrollViewer)) as SinacorScrollViewer;
        //    // Assina evento SizeChanged do scrollviewer
        //    _scrollViewer.SizeChanged += new SizeChangedEventHandler(scrollViewer_SizeChanged);
        //}

        //private void scrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
        //{
        //    // Sempre que o tamanho do scrollviewer mudar, deve recalcular as medidas do controle
        //    this.InvalidateMeasure();
        //}

        //protected override Size MeasureOverride(Size constraint)
        //{
        //    // Ao calcular as medidas do conteúdo da janela, como a janela possui um scrollviewer 
        //    // o parâmetro "constraint" vem como infinito e isso causa problemas com outros scrollviewers 
        //    // dentro da janela, como o scroll do DataGrid.
        //    // Para resolver o problema deve alterar o parâmetro "constraint" para as medidas do scrollviewer
        //    // da janela.
        //    if (_scrollViewer != null)
        //    {
        //        constraint.Width = (_scrollViewer.ActualWidth - 20 >= 0 ? _scrollViewer.ActualWidth - 20 : 0);
        //        constraint.Height = (_scrollViewer.ActualHeight - 20 >= 0 ? _scrollViewer.ActualHeight - 20 : 0);
        //    }

        //    Size size = base.MeasureOverride(constraint);

        //    return size;
        //}
    }
}
